package org.hepeng.workx.mybatis.event.consumer;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.hepeng.workx.extension.XLoader;
import org.hepeng.workx.mybatis.binding.MapperRegistryGetMapperObjectProcessor;
import org.hepeng.workx.mybatis.session.AttributeSqlSessionWrapper;
import org.hepeng.workx.util.proxy.Invoker;
import org.hepeng.workx.util.proxy.ProxyFactory;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author he peng
 */
public class AttributeSqlSessionWrapObjectProcessor implements MapperRegistryGetMapperObjectProcessor {

    private static final ProxyFactory PROXY_FACTORY = XLoader.getXLoader(ProxyFactory.class).getX();

    @Override
    public GetMapperPreProcessObject preProcess(GetMapperPreProcessObject preProcessObject) {

        Class<?> type = preProcessObject.getType();
        SqlSession sqlSession = preProcessObject.getSqlSession();

        AttributeSqlSessionWrapper attributeSqlSessionWrapper = new AttributeSqlSessionWrapper(sqlSession);
        attributeSqlSessionWrapper.setMapperInterface(type);

        List<Invoker> invokers = new LinkedList<>();
        invokers.add(attributeSqlSessionWrapper);

        List<Class<?>> interfaces = new ArrayList<>();
        interfaces.add(sqlSession.getClass());

        Object proxy;
        if (SqlSessionTemplate.class.isAssignableFrom(sqlSession.getClass())) {
            SqlSessionFactory sqlSessionFactory = preProcessObject.getConfiguration().getObjectFactory().create(SqlSessionFactory.class);
            List<Class<?>> constructorArgTypes = new ArrayList<>();
            constructorArgTypes.add(SqlSessionFactory.class);
            List<Object> constructorArgs = new ArrayList<>();
            constructorArgs.add(sqlSessionFactory);


            proxy = PROXY_FACTORY.createProxy(sqlSession.getClass() , null , constructorArgTypes, constructorArgs , invokers , null);
        } else {
            proxy = PROXY_FACTORY.createProxy(sqlSession.getClass() , null , null, null ,invokers ,null);
        }

        preProcessObject.setSqlSession((SqlSession) proxy);
        return preProcessObject;
    }

    @Override
    public GetMapperPostProcessObject postProcess(GetMapperPostProcessObject postProcessObject) {
        return postProcessObject;
    }
}
